package com.yc.music.manager;

import ohos.media.audio.AudioInterrupt;
import ohos.media.audio.AudioManager;
import ohos.media.audio.AudioRemoteException;

import com.yc.music.service.PlayService;
import com.yc.music.utils.MusicLogUtils;

/**
 * AudioFocusManager
 *
 * @since 2021-05-10
 */
public class AudioFocusManager implements AudioInterrupt.InterruptListener {
    private static final int COUNT_NUM = 2;
    private PlayService mPlayService;
    private AudioManager mAudioManager;
    /**
     * 是否因聚焦丢失瞬变而暂停
     */
    private boolean isPausedByFocusLossTransient;
    private int mTransientCanDuck;
    private AudioInterrupt audioInterrupt;

    /**
     * 初始化操作
     *
     * @param content playService对象
     */
    public AudioFocusManager(PlayService content) {
        mPlayService = content;
        mAudioManager = new AudioManager();
    }

    /**
     * 请求音频焦点，开始播放时候调用
     *
     * @return 是否抢占焦点
     */
    public boolean requestAudioFocus() {
        audioInterrupt = new AudioInterrupt();
        audioInterrupt.setInterruptListener(this);
        return mAudioManager.activateAudioInterrupt(audioInterrupt);
    }

    /**
     * 放弃音频焦点，销毁播放时候调用
     */
    public void abandonAudioFocus() {
        mAudioManager.deactivateAudioInterrupt(audioInterrupt);
    }

    /**
     * 当音频焦点发生变化的时候调用这个方法，在这里可以处理逻辑
     * 欢迎访问我的GitHub：https://github.com/yangchong211
     * 如果可以的话，请star吧
     *
     * @param focusChange 焦点改变
     * @param i1 i1
     */
    @Override
    public void onInterrupt(int focusChange, int i1) {
        int volume;
        switch (focusChange) {
            // 重新获得焦点
            case AudioInterrupt.INTERRUPT_HINT_RESUME:
                if (!willPlay() && isPausedByFocusLossTransient) {
                    mPlayService.playPause(); // 通话结束，恢复播放
                } // 获取音量
                try {
                    volume = mAudioManager.getVolume(AudioManager.AudioVolumeType.STREAM_MUSIC);
                    if (mTransientCanDuck > 0 && volume == mTransientCanDuck / COUNT_NUM) {
                        mAudioManager.setVolume(AudioManager.AudioVolumeType.STREAM_MUSIC, mTransientCanDuck); // 恢复音量
                    }
                } catch (AudioRemoteException e) {
                    MusicLogUtils.e(e.getMessage());
                }
                isPausedByFocusLossTransient = false;
                mTransientCanDuck = 0;
                break;
            case AudioInterrupt.INTERRUPT_HINT_PAUSE: // 永久丢失焦点，如被其他播放器抢占
                // 失去audio focus很长一段时间，必须停止所有的audio播放，清理资源
                if (willPlay()) {
                    forceStop();
                }
                break;
            case AudioInterrupt.INTERRUPT_HINT_STOP: // 短暂丢失焦点，比如来了电话或者微信视频音频聊天等等
                // 暂时失去audio focus，但是很快就会重新获得，在此状态应该暂停所有音频播放，但是不能清除资源
                if (willPlay()) {
                    forceStop();
                    isPausedByFocusLossTransient = true;
                }
                break;
            case AudioInterrupt.INTERRUPT_HINT_DUCK: // 瞬间丢失焦点，如通知
                // 暂时失去 audio focus，但是允许持续播放音频(以很小的声音)，不需要完全停止播放。
                // 音量减小为一半
                try {
                    volume = mAudioManager.getVolume(AudioManager.AudioVolumeType.STREAM_MUSIC);
                    if (willPlay() && volume > 0) {
                        mTransientCanDuck = volume;
                        mAudioManager.setVolume(AudioManager.AudioVolumeType.STREAM_MUSIC,
                            mTransientCanDuck / COUNT_NUM);
                    }
                } catch (AudioRemoteException e) {
                    MusicLogUtils.e(e.getMessage());
                }
                break;
            default:
                break;
        }
    }

    /**
     * 判断是否在播放或者准备播放
     *
     * @return return
     */
    private boolean willPlay() {
        // 当正在准备播放或者播放，则返回为true
        return mPlayService.isPreparing() || mPlayService.isPlaying();
    }

    private void forceStop() {
        if (mPlayService.isPreparing()) { // 当准备播放时，则停止播放
            mPlayService.stop(); // 当正在播放时，则暂停播放
        } else if (mPlayService.isPlaying()) {
            mPlayService.pause();
        }
    }
}
